/**
 * Copyright 2008-2009 HAN.BIFANG
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package han.bifang.business.dao;

import han.bifang.common.entity.SoaBusInnerService;
import han.bifang.common.entity.SoaDomain;
import han.bifang.common.entity.SoaJmsBinding;
import han.bifang.common.entity.SoaJmsBindingWrapper;
import han.bifang.common.entity.SoaNormalJms;
import han.bifang.common.entity.SoaService;
import han.bifang.common.entity.SoaServiceBus;
import han.bifang.common.entity.SoaServiceVersion;
import han.bifang.common.entity.SoaSoapBinding;
import han.bifang.common.exception.BifangErrorCode;
import han.bifang.common.exception.BifangException;
import han.bifang.common.persist.dao.DaoManager;
import han.bifang.common.persist.tx.Tx;
import han.bifang.common.persist.tx.TxManager;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @Author Kent
 */
public class ServiceBusDao {
	private static Log logger = LogFactory.getLog(ServiceBusDao.class);

	public static List getServiceBusByDomainId(String domainId)
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			String sql = "from SoaServiceBus s where s.domainId = ? ";
			List buses = DaoManager.getDao().find(sql, domainId);

			tx.commit();

			return buses;

		} catch (Throwable e) {
			logger.error("ServiceBusDao.getServiceBusByDomainId()", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"getServiceBusByDomainId() error", e);
		} finally {
			tx.end();
		}

	}

	public static SoaServiceBus getServiceBusByBusCode(String code)
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			String sql = "from SoaServiceBus s where s.code = ? ";
			List<SoaServiceBus> buses = (List<SoaServiceBus>) DaoManager
					.getDao().find(sql, code);

			tx.commit();
			if (buses.size() > 0)
				return buses.get(0);
			else
				return null;

		} catch (Throwable e) {
			logger.error("ServiceBusDao.getServiceBusByBusCode()", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"getServiceBusByBusCode() error", e);
		} finally {
			tx.end();
		}

	}

	public static void createServiceBus(SoaServiceBus bus)
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			String hql = "from SoaServiceBus s where s.code = ? and s.domainId = ?";
			Object[] o = new Object[] { bus.getCode(), bus.getDomainId() };
			List buses = DaoManager.getDao().find(hql, o);
			if (buses.size() > 0) {
				throw new BifangException(
						BifangErrorCode.BUS_CODE_EXISTS_ERROR,
						"SerivceBus code " + bus.getCode() + " exists.");

			}
			hql = "from SoaServiceBus s where s.name = ? and s.domainId = ?";
			o = new Object[] { bus.getName(), bus.getDomainId() };
			buses = DaoManager.getDao().find(hql, o);
			if (buses.size() > 0) {
				throw new BifangException(
						BifangErrorCode.BUS_NAME_EXISTS_ERROR,
						"SerivceBus name " + bus.getName() + " exists.");

			}

			DaoManager.getDao().save(bus);
			DaoManager.getDao().flush();
			tx.commit();

		} catch (BifangException e) {
			throw e;
		} catch (Throwable e) {
			logger.error("ServiceBusDao.createServiceBus()", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"createServiceBus() error", e);
		} finally {
			tx.end();
		}

	}

	public static void modifyServiceBus(SoaServiceBus bus)
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			String hql = "from SoaServiceBus s where s.code = ? ";
			List buses = DaoManager.getDao().find(hql, bus.getCode());
			if (buses.size() > 0) {
				SoaServiceBus t = (SoaServiceBus) buses.get(0);
				if (!t.getId().equals(bus.getId()))
					throw new BifangException(
							BifangErrorCode.BUS_CODE_EXISTS_ERROR,
							"SerivceBus code " + bus.getCode() + " exists.");

			}
			DaoManager.getDao().merge(bus);
			DaoManager.getDao().flush();
			tx.commit();

		} catch (Throwable e) {
			logger.error("ServiceBusDao.modifyServiceBus()", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"modifyServiceBus() error", e);
		} finally {
			tx.end();
		}

	}

	public static void removeServiceBus(SoaServiceBus bus)
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			DaoManager.getDao().delete(bus);
			DaoManager.getDao().flush();
			tx.commit();

		} catch (Throwable e) {
			logger.error("ServiceBusDao.removeServiceBus()", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"removeServiceBus() error", e);
		} finally {
			tx.end();
		}

	}

	public static void removeServiceBus(String busId) throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			SoaServiceBus bus = (SoaServiceBus) DaoManager.getDao().get(
					SoaServiceBus.class, busId);
			if (bus == null)
				throw new BifangException(
						BifangErrorCode.RECORD_NOT_EXISTS_ERROR,
						"SoaServiceBus[id=" + busId + "] doesn't exist.");
			DaoManager.getDao().delete(bus);
			DaoManager.getDao().flush();
			tx.commit();

		} catch (Throwable e) {
			logger.error("ServiceBusDao.removeServiceBus(String)", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"removeServiceBus(String) error", e);
		} finally {
			tx.end();
		}

	}

	public static SoaServiceBus getServiceBus(String busId)
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			SoaServiceBus bus = (SoaServiceBus) DaoManager.getDao().get(
					SoaServiceBus.class, busId);

			tx.commit();
			return bus;

		} catch (Throwable e) {
			logger.error("ServiceBusDao.getServiceBus(String)", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"getServiceBus(String) error", e);
		} finally {
			tx.end();
		}

	}

	public static List<SoaServiceBus> getLocalServiceBuses()
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			String hql = "from SoaDomain d where d.local=true";
			List<SoaDomain> ds = DaoManager.getDao().find(hql);
			
			hql = "from SoaServiceBus s where s.domainId = ?";
			List<SoaServiceBus> bs = DaoManager.getDao().find(hql, ds.get(0).getId());
			
			
			tx.commit();
			return bs;

		} catch (Throwable e) {
			logger.error("ServiceBusDao.getLocalServiceBuses()", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"getLocalServiceBuses() error", e);
		} finally {
			tx.end();
		}

	}

	public static boolean hasBindedServices(String serviceBusId)
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();

			String hql = "from SoaBusServiceRel s where s.compId.busId = ?";
			List l = DaoManager.getDao().find(hql, serviceBusId);
			tx.commit();

			if (l.size() > 2)// bus has two inner services to be bound.
				return true;

			return false;

		} catch (Throwable e) {
			logger.error("ServiceBusDao.hasBindedServices()", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"hasBindedServices() error", e);
		} finally {
			tx.end();
		}

	}

	public static SoaBusInnerService[] getInnerServices(String serviceBusId)
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			SoaBusInnerService[] ret = new SoaBusInnerService[2];
			String hql = "from SoaService s where s.busId = ?";
			List<SoaService> l = DaoManager.getDao().find(hql, serviceBusId);
			for (SoaService s : l) {
				SoaBusInnerService is = new SoaBusInnerService();
				is.setService(s);
				if (s.getServiceCode().endsWith("notify")) {
					ret[0] = is;
					hql = "select v.bindingId from SoaServiceVersion v where v.version = '"
							+ s.getDefaultVersion()
							+ "' and v.serviceId = '"
							+ s.getId() + "'";
					List<String> bid = DaoManager.getDao().find(hql);
					SoaJmsBindingWrapper w = new SoaJmsBindingWrapper();
					SoaJmsBinding o = (SoaJmsBinding) DaoManager.getDao().get(
							SoaJmsBinding.class, bid.get(0));
					w.setJmsBinding(o);
					SoaNormalJms j = (SoaNormalJms) DaoManager.getDao().get(
							SoaNormalJms.class, o.getInfoId());
					w.setInfo(j);
					is.setJmsBinding(w);
				} else {
					ret[1] = is;
					hql = "select v.bindingId from SoaServiceVersion v where v.version = '"
							+ s.getDefaultVersion()
							+ "' and v.serviceId = '"
							+ s.getId() + "'";
					List<String> bid = DaoManager.getDao().find(hql);
					hql = "from SoaSoapBinding b where b.id = ?";
					List<SoaSoapBinding> bb = DaoManager.getDao().find(hql,
							bid.get(0));
					is.setSoapBinding(bb.get(0));
				}

			}

			tx.commit();

			return ret;

		} catch (Throwable e) {
			logger.error("ServiceBusDao.getInnerServices()", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"getInnerServices() error", e);
		} finally {
			tx.end();
		}

	}

	public static void removeInnerServices(String serviceBusId)
			throws BifangException {
		Tx tx = null;

		try {
			tx = TxManager.start();
			SoaBusInnerService[] ret = new SoaBusInnerService[2];
			String hql = "from SoaService s where s.busId = ?";
			List<SoaService> l = DaoManager.getDao().find(hql, serviceBusId);
			for (SoaService s : l) {
				hql = " from SoaServiceVersion v where v.version = '"
						+ s.getDefaultVersion() + "' and v.serviceId = '"
						+ s.getId() + "'";
				List<SoaServiceVersion> bid = DaoManager.getDao().find(hql);
				if (s.getServiceCode().endsWith(".notify")) {
					hql = "from SoaJmsBinding b where b.id = ?";
					List<SoaJmsBinding> bb = DaoManager.getDao().find(hql,
							bid.get(0).getBindingId());
					hql = "from SoaNormalJms s where s.id = ?";
					List<SoaJmsBinding> bb1 = DaoManager.getDao().find(hql,
							bb.get(0).getInfoId());
					;
					DaoManager.getDao().delete(bb1.get(0));
					DaoManager.getDao().delete(bb.get(0));

				} else {
					hql = "from SoaSoapBinding b where b.id = ?";
					List<SoaSoapBinding> bb = DaoManager.getDao().find(hql,
							bid.get(0).getBindingId());
					DaoManager.getDao().delete(bb.get(0));
				}

				DaoManager.getDao().delete(bid.get(0));
				DaoManager.getDao().delete(s);
			}
			DaoManager.getDao().flush();
			tx.commit();

		} catch (Throwable e) {
			logger.error("ServiceBusDao.removeInnerServices()", e);
			tx.rollback();
			throw new BifangException(BifangErrorCode.DB_ERROR,
					"removeInnerServices() error", e);
		} finally {
			tx.end();
		}

	}
}
